package com.ms.game.rebate.db;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.Session;

import com.ms.game.rebate.RebateCoinData;
import com.ms.game.rebate.RebateModifyStatus;
import com.ms.game.rebate.RebateType;
import com.ms.game.rebate.RebateUtil;
import com.ms.player.PlayerNickNameParser;
import com.xpec.c4.db.basic.BasicGameDAO;
import com.xpec.c4.db.hibernate.manager.HibernateLogManager;
import com.xpec.c4.db.hibernate.manager.HibernateManager;
import com.xpec.c4.db.model.PlayerModel;
import com.xpec.c4.game.common.Helper;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.game.utility.GameUtility;

public class RebateDAO extends BasicGameDAO {
	private static Log log = LogFactory.getLog(RebateDAO.class);

	/**
	 * 保存實體對像 送禮通知
	 * 
	 * @param entity
	 *            待保存的實體對像
	 */
	public static boolean saveRebateModel(RebateModel model) {
		if (model == null) {
			return false;
		}
		Session session = HibernateManager.txBegin();
		session.save(model);
		return HibernateManager.txCommitFailRollbackClearSession();
	}
	
	/**
	 * 將本日的抽佣壘加到回饋金欄位
	 * 如果在下一次的刷新前有資料，就覆蓋，不然就新增一筆
	 */
	public static boolean updateOrSaveCommison(RebateModel saveModel){
		Session session = HibernateManager.txBegin();
		Query query = session.createQuery("from RebateModel where belongsDate =:date and uplineId = :Id and type =:type");
		query.setDate("date", saveModel.getBelongsDate());
		query.setParameter("Id", saveModel.getUplineId());
		query.setParameter("type", RebateType.COMMISSION.getId());
		RebateModel dbModel = (RebateModel)query.uniqueResult();
		if(dbModel == null){
			session.save(saveModel);
		}else{
			BigDecimal addCoin = Helper.add(dbModel.getTotalRebateCoin(),saveModel.getTotalRebateCoin());
			dbModel.setLastModifyTime(saveModel.getLastModifyTime());
			dbModel.setTotalRebateCoin(addCoin);
			session.update(dbModel);
		}
		return HibernateManager.txCommitFailRollbackClearSession();
	}
	
	/**
	 *	確認有多少抽傭回饋金可領取 
	 *	@param uplineId 要領取人的id
	 */
	public static HashMap<Date, RebateCoinData> checkCommisonRebateData(GUID uplineId){
		Session session = HibernateManager.getSession();
		Query query = session.createQuery("from RebateModel where type =:type and uplineId = :Id and belongsDate <= :date and status = :status");
		query.setParameter("Id", uplineId.toString());
		query.setParameter("status", RebateModifyStatus.NOT_RECEIVE);
		query.setDate("date", GameUtility.getEventLastFlushTime(RebateUtil.getCommisonFlushTimeFormat()));
		query.setParameter("type", RebateType.COMMISSION.getId());
		ArrayList<RebateModel> models = (ArrayList<RebateModel>)query.list();
		HibernateManager.endSession();
		
		HashMap<Date, RebateCoinData> commisonDatas = new HashMap<Date, RebateCoinData>();
		
		if(models.size() > 0){
			for (RebateModel model : models) {
				RebateCoinData data = new RebateCoinData();
				Date key = model.getBelongsDate();
				if (commisonDatas.containsKey(key)) {
					data = commisonDatas.get(key);
					data.setRebateCoins(Helper.add(data.getRebateCoins(), model.getTotalRebateCoin()));
				} else {
					data.setSuccess(true);
					data.setRebateCoins(model.getTotalRebateCoin());
					data.setBelongsDate(model.getBelongsDate().getTime());
					data.setEndDate(model.getEndDate().getTime());
				}
				commisonDatas.put(key,data);
			}
		}
		return commisonDatas;
	}

	public static ArrayList<RebateModel>  checkUplineInviteRewardData(GUID uplineId) {
		Session session = HibernateManager.txBegin();
		Query query  = session.createQuery("from RebateModel where uplineId =:Id and (type = :type or type = :type2) and belongsDate <= :date and status = :status");
		query.setParameter("Id", uplineId.toString());
		query.setParameter("status", RebateModifyStatus.NOT_RECEIVE);
		query.setDate("date", GameUtility.getEventLastFlushTime(RebateUtil.getCommisonFlushTimeFormat()));
		query.setParameter("type", RebateType.UPLINE_INVITE_AWARD.getId());
		query.setParameter("type2", RebateType.UPLINE_INVITE_AWARD_DISTRIBUTOR.getId());
		ArrayList<RebateModel> models = (ArrayList<RebateModel>)query.list();

		HibernateManager.txCommitFailRollbackClearSession();
		
		return models;
	}
	
	/**
	 * 取得抽佣回饋金並標記成已領取
	 * @param uplineId 要領取人的id
	 * @return
	 */
	public static RebateModel getCommisonRebateCoinMarkReceived(GUID playerID, long time) {
		Session session = HibernateManager.txBegin();
		Query query = null;
		query = session.createQuery("from RebateModel where uplineId = :Id and type =:type and endDate =:time and status = :status");
		query.setParameter("Id", playerID.toString());
		query.setDate("time", GameUtility.longToDate(time));
		query.setParameter("status", RebateModifyStatus.NOT_RECEIVE);
		query.setParameter("type", RebateType.COMMISSION.getId());
		RebateModel model = (RebateModel) query.uniqueResult();
		if (model != null) {
			model.setStatus(RebateModifyStatus.HAVE_RECEIVED);
			model.setLastModifyTime(Calendar.getInstance());
			session.update(model);
		}
		HibernateManager.txCommitFailRollbackClearSession();
		return model;
	}
	
	
	
	
	
	public static ArrayList<RebateModel> getAllReabteDatas(GUID playerID) {
		Session session = HibernateManager.txBegin();

		Query query = session.createQuery("from RebateModel where uplineId = :Id and (belongsDate between :lastKeep and :today) and status = :status");
		query.setParameter("Id", playerID.toString());
		query.setDate("today", GameUtility.getEventLastFlushTime(RebateUtil.getCommisonFlushTimeFormat()));
		query.setDate("lastKeep", getLastKeepDate());
		query.setParameter("status", RebateModifyStatus.NOT_RECEIVE);
		return  (ArrayList<RebateModel>) query.list();
	}

	public static void markOutdatesRebateData() {
		Date deleteTime = getLastKeepDate();
		
		//清除過時資料 (上一次刷新之前的資料都要清除)
		Session session = HibernateManager.txBegin();
		Query query = session.createQuery("update RebateModel set status =:statusAfterChange where belongsDate  < :deleteTime and status = :statusBeforeChange");
		query.setDate("deleteTime", deleteTime);
		query.setParameter("statusAfterChange",RebateModifyStatus.DELETED);
		query.setParameter("statusBeforeChange",RebateModifyStatus.NOT_RECEIVE);
		query.executeUpdate();
		boolean result = HibernateManager.txCommitFailRollbackClearSession();
		
		Session logSession = HibernateLogManager.txBegin();
		ClearRebateLogModel log = new ClearRebateLogModel();
		log.setSuccess(result);
		logSession.save(log);
		HibernateLogManager.txCommitFailRollbackClearSession();
		
	}
	
	public static RebateModel getUplineInviteRewardMarkReceived(GUID playerId, String downlineId) {
		Session session = HibernateManager.txBegin();
		Query query = null;
		query = session.createQuery("from RebateModel where uplineId =:uplineId and downlineId =:downlineId and (type = :type or type = :type2) and status = :status");
		query.setParameter("uplineId", playerId.toString());
		query.setParameter("downlineId", downlineId);
		query.setParameter("status", RebateModifyStatus.NOT_RECEIVE);
		query.setParameter("type", RebateType.UPLINE_INVITE_AWARD.getId());
		query.setParameter("type2", RebateType.UPLINE_INVITE_AWARD_DISTRIBUTOR.getId());
		
		RebateModel model = null;
		try {
			//2017-08-11 這裡雖然是用or搜尋，但邀請碼的使用規則上一定只會撈到一個model
			//但若真的不知道甚麼原因結果不是只有一筆會使query.uniqueResult()出現例外
			model = (RebateModel) query.uniqueResult();
		} catch (Exception e) {
			if(log.isErrorEnabled()){
				log.error("can't find unique result in DB, playerGUID:"+playerId.toString()+", downlineId:"+downlineId, e);
			}
		}
		
		if (model != null) {
			model.setStatus(RebateModifyStatus.HAVE_RECEIVED);
			model.setLastModifyTime(Calendar.getInstance());
			session.update(model);
		}
		
		HibernateManager.txCommitFailRollbackClearSession();
		
		return model;
	}
	
	public static boolean updateRebateModelStatus(RebateModel model, int status){
		Session session = HibernateManager.txBegin();
		Query query = session.createQuery("Update RebateModel set status =:STATUS where db_id =:DBID");
		query.setParameter("STATUS", status);
		query.setParameter("DBID", model.getDb_id());
		query.executeUpdate();
		return HibernateManager.txCommitFailRollbackClearSession();
	}
	
	public static boolean updateRebateModelStatus(ArrayList<RebateModel> models, int status){
		Session session = HibernateManager.txBegin();
		for (RebateModel rebateModel : models) {
			Query query = session.createQuery("Update RebateModel set status =:STATUS ,lastModifyTime =:MODIFYTIME  where db_id =:DBID");
			query.setParameter("STATUS", status);
			query.setCalendar("MODIFYTIME", Calendar.getInstance());
			query.setParameter("DBID", rebateModel.getDb_id());
			query.executeUpdate();
		}
		return HibernateManager.txCommitFailRollbackClearSession();
	}
	
	private static Date getLastKeepDate(){
		Date date = GameUtility.getEventLastFlushTime(RebateUtil.getCommisonFlushTimeFormat());
		//當日也算所以+1
		date.setDate(date.getDate()- RebateUtil.getCommisonKeepDays() + 1);
		return date;
	}
	
	public static boolean updateRebateModel(RebateModel model){
		Session session = HibernateManager.getSession();
		session.update(model);
		return HibernateManager.txCommitFailRollbackClearSession();
	}

	public static boolean updateRebateModels(ArrayList<RebateModel> model) {
		Session session = HibernateManager.getSession();
		for (RebateModel rebateModel : model) {
			System.err.println(rebateModel.getStatus());
			session.update(rebateModel);
		}
		return HibernateManager.txCommitFailRollbackClearSession();
	}
	
	/**
	 * 給上線獎勵
	 */
	public static void addUplineInviteCodeReward(PlayerModel model, String uplineId ,int rebateCoin, RebateType rebateType){
		RebateModel rebateModel = makeRebateModel(model, uplineId, rebateCoin, rebateType);
		Session session = HibernateManager.txBegin();
		session.save(rebateModel);
		HibernateManager.txCommitFailRollbackClearSession();
	}
	
	private static RebateModel makeRebateModel(PlayerModel model , String uplineId ,int rebateCoin, RebateType rebateType){
		RebateModel rebateModel = new RebateModel();
		rebateModel.setUplineId(uplineId);
		//當下配發
		rebateModel.setBelongsDate(GameUtility.getEventLastFlushTime(RebateUtil.getCommisonFlushTimeFormat()));
		rebateModel.setType(rebateType.getId());
		rebateModel.setTypeDesc(rebateType.getDesc());
		Date endDate = GameUtility.getEventLastFlushTime(RebateUtil.getCommisonFlushTimeFormat());
		endDate.setDate(endDate.getDate() + 30);
		rebateModel.setEndDate(endDate);
		rebateModel.setDownlineId(model.getGuid());
		rebateModel.setDownlineName(PlayerNickNameParser.mergeNickName(model.getName(), model.getNameNumber()));
		rebateModel.setTotalRebateCoin(new BigDecimal(rebateCoin));
		return rebateModel;
	}
}
